﻿using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Linq;

namespace Keyki.NefClass.Kernel
{
	public static class Utility
	{
		public static Boolean IsEmpty<T>(this IEnumerable<T> source)
		{
			//return source.Count() == 0;

			if (source == null)
				return true; // or throw an exception
			return !source.Any();
		}//IsEmpty

		/// <summary>
		/// VAR(X) = M(X^2) - (M(X)^2)
		/// </summary>
		/// <param name="source"></param>
		/// <returns>Variance value</returns>
		public static Double Variance(this IEnumerable<Double> source)
		{
			return source.Select(element => element * element).Average() - Math.Pow(source.Average(), 2);
		}//Variance

		/// <summary>
		/// VAR(X) = M(X^2) - (M(X)^2)
		/// </summary>
		/// <param name="source"></param>
		/// <param name="mean">Average value</param>
		/// <returns>Variance value</returns>
		public static Double Variance(this IEnumerable<Double> source, double mean)
		{
			return source.Select(element => element * element).Average() - Math.Pow(mean, 2);
		}//Variance

		/// <summary>
		/// Return Key of max element in the IEnumerable
		/// </summary>
		/// <param name="source"></param>
		/// <returns></returns>
		public static Int32 ArgMax(this IEnumerable<Double> source)
		{
			var max = source.Max();
			int i = 0;

			source.First(value =>
			             	{
			             		i++;
			             		return value == max;
			             	});

			return i - 1;
		}

		/// <summary>
		/// Return Key of min element in the IEnumerable
		/// </summary>
		/// <param name="source"></param>
		/// <returns></returns>
		public static Int32 ArgMin(this IEnumerable<Double> source)
		{
			var min = source.Min();
			int i = 0;

			source.First(value =>
			{
				i++;
				return value == min;
			});

			return i - 1;
		}

		/// <summary>
		/// Return subset from start element to end elemetn, if end more than source.Count than take all of elements
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="source"></param>
		/// <param name="start"></param>
		/// <param name="end"></param>
		/// <returns></returns>
		public static IEnumerable<T> GetRange<T>(this IEnumerable<T> source, int start, int end)
		{
			return source.Skip(start).Take(end - start);
		}//GetRange

		/// <summary>
		/// Return string of collection elements
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="source"></param>
		/// <returns></returns>
		public static String GetString<T>(this IEnumerable<T> source)
		{
			StringBuilder builder = new StringBuilder(source.Count());
			foreach (T element in source)
			{
				builder.Append(element.ToString() + " ");
			}
			return builder.ToString();
		}//GetString

	}//Utility
}